#include "ArbolDecision.h"
#include "ListaPrincipal.h"
#include "CalculadorGanacias.h"
#include "NodoArbol.h"

ArbolDecision::ArbolDecision(ListaPrincipal* matrizInformacion) {

	this->matrizInformacion = matrizInformacion;
	calculador = new CalculadorGanacias(matrizInformacion);
	Lista<int>* todosLosParrafos = obtenerIdParrafos(getTodosLosParrafos());

	raiz = evaluarSubArbol(todosLosParrafos,0);
}

Lista<int>* ArbolDecision::getTodosLosParrafos() {

	Lista<int> *idParrafos = new Lista<int>();
	PalabraConFrecuencias* primerPalabra = this->matrizInformacion->getLista()->iterador().siguiente();
	int tam = primerPalabra->getListaFrecuencias()->tamanio();

	for (int i = 1; i <= tam; i++) {
		idParrafos->agregar(i);
	}

	return idParrafos;
}

ArbolDecision::~ArbolDecision() {
	delete calculador;
}

NodoArbol* ArbolDecision::evaluarSubArbol(Lista<int> *idParrafos,int profundidad) {

	string mejorPalabra = calculador->devolverMejorPalabra(idParrafos);



	NodoArbol* raizSubArbol = new NodoArbol(mejorPalabra, idParrafos);

	//Si no se puede decidir autor calcular nodos hijos
	if (seguirAvanzando(idParrafos,profundidad)) {
		profundidad++;

		raizSubArbol->izquierdo = evaluarSubArbol(obtenerIdParrafos(idParrafos,mejorPalabra,0),profundidad);
		raizSubArbol->derecho = evaluarSubArbol(obtenerIdParrafos(idParrafos,mejorPalabra,1),profundidad);
	} else {
		raizSubArbol->setAutor(definirAutor(idParrafos));
	}

	return raizSubArbol;
}

bool ArbolDecision::seguirAvanzando(Lista<int> *idParrafos,int produnfidad) {

	if (produnfidad >= 4) {
		return false;
	}

	return true;
}

string ArbolDecision::definirAutor(Lista<int> *idParrafos) {

	int cantMarx = 0;
	int cantWeber = 0;

	PalabraConFrecuencias* primerPalabra = this->matrizInformacion->getLista()->iterador().siguiente();
	IteradorLista<FrecuenciaParrafo*> it = primerPalabra->getListaFrecuencias();

	int contador = 0;

	while(it.tieneSiguiente()){

		contador++;
		FrecuenciaParrafo* actual = it.siguiente();

		if(existeParrafo(contador, idParrafos)){
			if(actual->getAutor() == "M")
				cantMarx++;
			else if(actual->getAutor() == "W") {
				cantWeber++;
			}
		}
	}

	if (cantMarx < cantWeber) {
		return "W";
	} else  {
		return "M";
	}
}

char ArbolDecision::predecirAutor(string parrafo) {

	NodoArbol* curr = this->raiz;

	while (true) {

		if (curr->izquierdo == NULL || curr->derecho == NULL) {
			return curr->autor[0];
		}

		if (parrafo.find(curr->palabra) == string::npos) {
			curr = curr->izquierdo;
		} else {
			curr = curr->derecho;
		}
	}

	return 'M';
}

Lista<int>* ArbolDecision::obtenerIdParrafos(Lista<int> *idParrafos,string palabra,int estado) {

	if (estado == -1) {
		return idParrafos;
	} else {

		Lista<int>* nuevosParrafos = new Lista<int>();
		IteradorLista<PalabraConFrecuencias*> it = this->matrizInformacion->getLista()->iterador();
		PalabraConFrecuencias* palabraBuscada = NULL;

		while (it.tieneSiguiente()) {
			PalabraConFrecuencias* actual = it.siguiente();

			if (actual->getPalabra() == palabra) {
				palabraBuscada = actual;
				break;
			}
		}

		if (palabraBuscada == NULL) {
			cerr << "Error: no se pudo encontrar la palabra buscada" << endl;
		}

		IteradorLista<FrecuenciaParrafo*> itParrafo = palabraBuscada->getListaFrecuencias()->iterador();
		int cont = 1;

		while (itParrafo.tieneSiguiente()) {
			FrecuenciaParrafo* frecActual = itParrafo.siguiente();

			if (frecActual->getContador()) {

				if (estado) {
					if (existeParrafo(cont,idParrafos)) {
						nuevosParrafos->agregar(cont);
					}
				}
			} else {
				if (!estado) {
					if (existeParrafo(cont,idParrafos)) {
						nuevosParrafos->agregar(cont);
					}
				}
			}
			cont++;
		}
		return nuevosParrafos;
	}

}

bool ArbolDecision::existeParrafo(int id, Lista<int> *idParrafos) {

	IteradorLista<int> it = idParrafos->iterador();

	while (it.tieneSiguiente()) {
		int actual = it.siguiente();

		if (actual == id) {
			return true;
		}
	}

	return false;
}
